home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / COMMON.ZIP / SERIAL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-08  |  17.5 KB  |  847 lines

  1. /*
  2.  
  3. Compiled and tested with Borland C++ 3.0, 3.1
  4. Uses INLINE assembly (ick)!
  5.  
  6. Support com1 thru 4 at standard addresses and IRQ's,
  7. 300 ->115200 baud
  8.  
  9. This file contains time tested serial port I/O
  10. stuff. Most of this came from "Al Williams: DOS 5 for Developers" book
  11. which is excelent! The serial code in the book had one minor bug
  12. which caused chars to be dropped rarely, but that is fixed.
  13.  
  14. To use with a modem you need a few simple routines to dial etc...
  15. but this just involes sending the correct strings to the modem and listening
  16. for the response.
  17.  
  18. .e.g. send ATDT555-555 to the modem, then wait or a respones
  19. which will be something like CONNECT, BUSY, NO DIALTONE, etc...
  20. don't wait forever :) for a response!
  21.  
  22. Feel free to use this in any project, commercial or otherwise.
  23.  
  24. Alec Russell.
  25.  
  26. */
  27.  
  28. /* start of serio.h -------------------------------------------------- */
  29.  
  30. /****************************************************************
  31.  *                                                              *
  32.  * File: serio.h                                                *
  33.  *                                                              *
  34.  * Description:                                                 *
  35.  * Header file for programs that use SERIO.C                    *
  36.  *                                                              *
  37.  ****************************************************************/
  38.  
  39. #ifndef SERIOHEADER
  40. #define SERIOHEADER 
  41.  
  42. /* define for sio_error */
  43. enum SIO_ERROR_CODES
  44.     {
  45.     SIO_IS_OK,         /* 0 == NO ERROR */
  46.     SIO_OVERFLOW,
  47.     SIO_NO_COMM,
  48.     SIO_BAD_BAUD,
  49.     SIO_NO_IRQ,
  50.     SIO_BAD_BITS,
  51.     SIO_BAD_PARITY
  52.     };
  53.  
  54. typedef struct
  55.     {
  56.     int comport;   /* comm 1,2,3,4 */
  57.     int irq;       /* irq, set to 0 for default */
  58.     int baud;      /* see below */
  59.     int bits;      /* data bits */
  60.     int parity;    /* see below */
  61.     int stops;     /* stop bits */
  62.     }
  63. serial_232_t;
  64.  
  65. /*
  66.     baud:
  67.  
  68.         0 -   110
  69.         1 -   150
  70.         2 -   300
  71.         3 -  1200
  72.         4 -  2400
  73.         5 -  4800
  74.         6 -  9600
  75.         7 - 19200
  76.         
  77.     parity:
  78.         0 - none
  79.         1 - odd
  80.         2 - even
  81.         3 - mark
  82.         4 - space
  83.  
  84. */
  85.  
  86. enum
  87.     {
  88.     BAUD_110,
  89.     BAUD_150,
  90.     BAUD_300,
  91.     BAUD_1200,
  92.     BAUD_2400,
  93.     BAUD_4800,
  94.     BAUD_9600,
  95.     BAUD_19200,
  96.     BAUD_38400,
  97.     BAUD_57600,
  98.     BAUD_115200
  99.     };
  100.  
  101. enum
  102.     {
  103.     PARITY_NONE, 
  104.     PARITY_ODD, 
  105.     PARITY_EVEN, 
  106.     PARITY_MARK, 
  107.     PARITY_SPACE 
  108.     };
  109.  
  110. /*
  111.  
  112.     ansi_str[]
  113.  
  114.     0   Up
  115.     1   Down
  116.     2   Right
  117.     3   Left
  118.     4   home
  119.     5   end
  120.     6   pg up
  121.     7   pg dn
  122.     8   ... undefined
  123.  
  124. */
  125.  
  126. /* ------------------ misc functions ------------------ */
  127.  
  128. /* Send a break */ 
  129. void sio_sendbreak(void);
  130.  
  131.  
  132. /* Check for character available (non-zero means char ready) */
  133. int char_ready_232(void);
  134.  
  135.  
  136. /* ------------- main functions ------------------------ */
  137.  
  138. /* wait until char is ready to be read */
  139. int get_232_wait(void);
  140.  
  141. /* returns -2 for break, -1 if no char ready */ 
  142. int get_232(void);
  143.  
  144. int peek_232x(void);
  145. int peek_232(void);
  146.  
  147.  
  148. /* write a character. returns 0 if successful, -1 if error  */
  149. int send_232(unsigned int c);
  150.  
  151. /* startup comport, install intrpt handler */
  152. int init_232(serial_232_t *sr);
  153.  
  154. /* CALL THIS FUNCTION BEFORE PROGRAM EXIT! */ 
  155. void deinit_232(void);
  156.  
  157. /* clear transmit, and recieve ques */
  158. void flush_232_xmit(void);
  159. void flush_232_rcv(void);
  160.  
  161.  
  162. /* End of header */ 
  163. #endif
  164.  
  165. /* ---------------- end of serio.h ------------------------------------ */
  166.  
  167. /* --------------------- start of serial.c ---------------------------- */
  168. /*
  169.  
  170. Alec Russell
  171.  
  172. low level serial stuff
  173.  
  174. Nov 30, 1992 - AR fixed a bug causing chars to be missed when transmiting
  175.                   in send_232()
  176.  
  177. */
  178.  
  179. #pragma inline
  180.  
  181. #include <stdio.h>
  182. #include <stdlib.h>
  183. #include <time.h>
  184. #include <ctype.h>
  185. #include <dos.h>
  186. #include <bios.h>
  187.  
  188. #include "serio.h"
  189.  
  190. #define TICKS        (*(volatile unsigned long far *)(0x0040006CL))
  191.  
  192. static void xmit(void);
  193. static void rcv(void);
  194. void msr(void);
  195. static void linestat(void);
  196.  
  197. static unsigned char force_transmit_ready;       /* flag to indicate tranmitter needs service */
  198.  
  199.  
  200. #define BUFFERLEN 2048
  201.  
  202. /* ticks to hold a break */
  203. #define BRKTIME 5
  204.  
  205.  
  206. /* base address of UART I/O */
  207. static int uart_adrs;
  208.  
  209.  
  210. /* IRQ & mask bit for PIC */
  211. static int irqmask, irqnum;
  212.  
  213.  
  214. #define XOFF 19
  215. #define XON 17
  216.  
  217.  
  218. /* global variables of interest to user's program */
  219. int sio_error=0;     /* see serio.h  sio_error_codes */
  220. int sio_errct=0;     /* overflow count */
  221.  
  222.  
  223. /* set to 1 when break occurs */
  224. int sio_break=0;
  225.  
  226.  
  227. unsigned char sio_linestat;                  /* line status */
  228.  
  229.  
  230. unsigned char sio_modemstat;                 /* modem status */
  231.  
  232.  
  233. /* --- turn xon/xoff on off with this */
  234. // int sio_doxoff=0;                  /* set xon/xoff mode on */
  235.  
  236.  
  237. /* if 1, get_232() returns -2 if break occured */
  238. int sio_brkmode=0;
  239.  
  240.  
  241. #define DATA_REG 0
  242. /* interrupt enable register */
  243. #define IER 1
  244. #define IIR 2                      /* interrupt id register */
  245. #define LCR 3                      /* line control register */
  246. #define MCR 4                      /* modem control register */
  247. #define LSR 5                      /* line status register */
  248. #define MSR 6                      /* modem status register */
  249.  
  250. #define MCR_RTS 0x02               /* MCR register RTS bit */
  251.  
  252. /* Define two circular buffers */
  253. static unsigned char xmitbuf[BUFFERLEN+1];
  254. static unsigned char rcvbuf[BUFFERLEN+1];
  255.  
  256.  
  257. static unsigned int xmithead=0,xmittail=0;
  258. static unsigned int xmitlen=0;
  259.  
  260.  
  261.  
  262.  
  263. static unsigned int rcvhead=0,rcvtail=0;
  264. static unsigned int rcvlen=0;
  265.  
  266.  
  267. // static int sentxoff=0,sendxoff=0,sendxon=0;
  268. // static int gotxoff=0;
  269.  
  270. static void (interrupt far *oldirq)(void);
  271.  
  272. /* baud rate table */
  273. static unsigned int baud_table[]=
  274.     {
  275.     0x417,  /* 110   baud */
  276.     0x300,  /* 150   baud */
  277.     0x180,  /* 300   baud */
  278.     0x60,   /* 1200  baud */
  279.     0x30,   /* 2400  baud */
  280.     0x18,   /* 4800  baud */
  281.     0xc,    /* 9600  baud */
  282.     0x6,    /* 19200 baud hmm... is the word "baud" redundant? */
  283.     0x3,    /* 38400 */
  284.     0x2,    /* 57600 */
  285.     0x1     /* 115200 */
  286.    };
  287.  
  288. // NOTE!!!!!!!!!
  289. // there is a way to look these up from the BIOS, but it isn't very reliable
  290. // so I hard coded these addresses!
  291.  
  292. static unsigned int irq_adr_table[]=
  293.    {
  294.    0x3f8,
  295.    0x2f8,
  296.    0x3e8,
  297.    0x2e8
  298.    };
  299.  
  300. /* ===================================================================== */
  301.  
  302. /* ------------------ start basic serial of functions ------------------ */
  303.  
  304.  
  305. /*
  306.     returns:
  307.         0 if ok
  308.         1 if less than FILL space bytes left in buffer
  309.         2 if full
  310.  
  311. */
  312. /* ---------------------- put_rcv_que() -------------------- May 29,1992 */
  313. int put_rcv_que(unsigned char c)
  314. {
  315.     int ret_code;
  316.  
  317.     if ( rcvlen == BUFFERLEN )
  318.         {
  319.         /* throw away oldest data, put in new data */
  320.         ret_code=2;
  321.  
  322.         rcvbuf[rcvtail]=c;
  323.  
  324.         ++rcvhead;
  325.         if ( rcvhead == BUFFERLEN )
  326.             rcvhead=0;
  327.         ++rcvtail;
  328.         if ( rcvtail == BUFFERLEN )
  329.             rcvtail=0;
  330.         }
  331.     else
  332.         {
  333.         /* put new data in que */
  334.         /*
  335.         if ( rcvlen > (BUFFERLEN - FILL) )
  336.             ret_code=1;
  337.         else
  338.         */
  339.  
  340.         ret_code=0;
  341.  
  342.         rcvbuf[rcvtail]=c;
  343.         ++rcvtail;
  344.         if ( rcvtail == BUFFERLEN )
  345.             rcvtail=0;
  346.         ++rcvlen;
  347.         }
  348.  
  349.     return(ret_code);
  350. }
  351.  
  352.  
  353. /*
  354.     returns:
  355.         char if ok
  356.         -1 if que empty
  357. */
  358. /* ---------------------- get_rcv_que() -------------------- May 29,1992 */
  359. unsigned int get_rcv_que(void)
  360. {
  361.     unsigned int c;
  362.  
  363.     if ( rcvlen == 0 )
  364.         return(-1);
  365.  
  366.     c=rcvbuf[rcvhead];
  367.     ++rcvhead;
  368.     if ( rcvhead == BUFFERLEN )
  369.         rcvhead=0;
  370.     --rcvlen;
  371.  
  372.     return(c);
  373. }
  374.  
  375.  
  376. /*
  377.     returns:
  378.         0 if ok
  379.         1 if less than FILL space bytes left in buffer
  380.         2 if full
  381.  
  382. */
  383. /* ---------------------- put_xmit_que() -------------------- May 29,1992 */
  384. int put_xmit_que(unsigned char c)
  385. {
  386.     int ret_code;
  387.  
  388.     if ( xmitlen == BUFFERLEN )
  389.         {
  390.         /* throw away oldest data, put in new data */
  391.         ret_code=2;
  392.         xmitbuf[xmittail]=c;
  393.         ++xmithead;
  394.         if ( xmithead == BUFFERLEN )
  395.             xmithead=0;
  396.         ++xmittail;
  397.         if ( xmittail == BUFFERLEN )
  398.             xmittail=0;
  399.         }
  400.     else
  401.         {
  402.         /* put new data in que */
  403.         /*
  404.         if ( xmitlen > (BUFFERLEN - FILL) )
  405.             ret_code=1;
  406.         else
  407.         */
  408.  
  409.         ret_code=0;
  410.  
  411.         xmitbuf[xmittail]=c;
  412.         ++xmittail;
  413.         if ( xmittail == BUFFERLEN )
  414.             xmittail=0;
  415.         ++xmitlen;
  416.         }
  417.  
  418.     return(ret_code);
  419. }
  420.  
  421.  
  422. /*
  423.     returns:
  424.         char if ok
  425.         -1 if que empty
  426. */
  427. /* ---------------------- get_xmit_que() -------------------- May 29,1992 */
  428. unsigned int get_xmit_que(void)
  429. {
  430.     unsigned int c;
  431.  
  432.     if ( xmitlen == 0 )
  433.         return(-1);
  434.  
  435.     c=xmitbuf[xmithead];
  436.     ++xmithead;
  437.     if ( xmithead == BUFFERLEN )
  438.         xmithead=0;
  439.  
  440.     --xmitlen;
  441.  
  442.     return(c);
  443. }
  444.  
  445.  
  446. /* nuke rcv buffer, and clear error flags */
  447. /* ---------------------- flush_232_rcv() ------------------ May 28,1992 */
  448. void flush_232_rcv(void)
  449. {
  450.     rcvhead=rcvtail=0;
  451.     sio_error=sio_errct=0;
  452.     rcvlen=0;
  453. }
  454.  
  455. /* nuke xmit buffer, attempt to send everything 1st */
  456. /* ---------------------- flush_232_xmit() ------------------ May 28,1992 */
  457. void flush_232_xmit(void)
  458. {
  459.    unsigned long t1;
  460.  
  461.    t1=TICKS;
  462.    t1+=200;
  463.  
  464.    while ( xmitlen && TICKS < t1 )
  465.       ;
  466.  
  467.     sio_error=sio_errct=0;
  468.     xmithead=xmittail=0;
  469.     xmitlen=0;
  470. }
  471.  
  472.  
  473.  
  474. /*
  475.  
  476.     this gets called whenever the UART generates an interupt
  477.  
  478. */
  479. /* ISR for UART interrupt */
  480. void far interrupt comint(void)
  481. {
  482.     int intstat;
  483.  
  484.     force_transmit_ready = 0;
  485.  
  486.     intstat=inportb(uart_adrs+IIR);
  487.  
  488.     while ( !(intstat & 1) )
  489.         {
  490.         switch ( intstat & 0x07)
  491.             {
  492.             case 0x02:
  493.                 xmit();
  494.                 break;
  495.  
  496.             case 0x04:
  497.                 rcv();
  498.                 break;
  499.  
  500.             case 0x06:
  501.                 linestat();
  502.                 break;
  503.  
  504.             case 0:
  505.                 msr();
  506.                 break;
  507.             }
  508.  
  509.         intstat=inportb(uart_adrs+IIR);
  510.         }
  511.  
  512.  
  513.     if ( force_transmit_ready )
  514.         xmit();
  515.  
  516.     outportb(0x20,0x20);                /* reset PIC */
  517. }
  518.  
  519.  
  520. /* Handle Modem Status interrupts - used to detect online status */
  521. void msr(void)
  522.    {
  523.    sio_modemstat=inportb(uart_adrs+MSR);
  524.    }
  525.  
  526.  
  527. /* Handle Line Status interrupts */
  528. static void linestat(void)
  529. {
  530.     sio_linestat=inportb(uart_adrs+LSR);
  531.     if ( sio_linestat & 0x10 )
  532.         sio_break=1;
  533. }
  534.  
  535.  
  536.  
  537. /* Attempt to transmit character */
  538. static void xmit(void)
  539. {
  540.     unsigned int c;
  541.  
  542.     force_transmit_ready = 0;
  543.  
  544.     if ( xmitlen == 0 )
  545.         return;
  546.  
  547.     /* UART not ready to transmit */
  548.     if ( !(inportb(uart_adrs+LSR) & 0x20) )
  549.         return;
  550.  
  551.     /* send next char in the buffer */
  552.     c=get_xmit_que();
  553.     outportb(uart_adrs+DATA_REG, (unsigned char)c);
  554. }
  555.  
  556.  
  557. /* Attempt to receive a character */
  558. static void rcv(void)
  559. {
  560.     unsigned int c, status;
  561.  
  562.     /* UART not ready to rcv */
  563.     while ( (status=inportb(uart_adrs+LSR)) & 1 )
  564.         {
  565.         /* Correct for possible loss of transmit interrupt from IIR register */   
  566.         if ( status & 0x20 )
  567.           force_transmit_ready = 1;
  568.  
  569.         if ( rcvlen == BUFFERLEN )
  570.             {
  571.             /*  buffer overflow */
  572.             sio_error=SIO_OVERFLOW;
  573.             sio_errct++;
  574.             }
  575.  
  576.         c=inportb(uart_adrs+DATA_REG);
  577.         put_rcv_que((unsigned char)c);
  578.         }
  579.  
  580.     return;
  581. }
  582.  
  583. /* delay used for sending a break */
  584. static void t_delay(int ticks)
  585. {
  586.    clock_t tick0;
  587.  
  588.    tick0=clock()+ticks;
  589.  
  590.    while ( clock() < tick0 )
  591.         ;
  592. }
  593.  
  594.  
  595. /* write a character. returns 0 if successful, -1 if error  */
  596. int send_232(unsigned int c)
  597. {
  598.  
  599.     /* wait until some room in buffer */
  600.     while ( xmitlen == BUFFERLEN )
  601.         ;
  602.  
  603.     put_xmit_que(c);
  604.  
  605.     /* Call xmit in case transmitter has been idle for
  606.        a while. If transmitter is busy, xmit won't do
  607.        anything
  608.     */
  609.  
  610.     asm cli
  611.  
  612.     xmit();
  613.  
  614.     asm sti
  615.  
  616.     return 0;
  617. }
  618.  
  619.  
  620. /* Check for character available (non-zero means char ready) */
  621. int char_ready_232(void)
  622.    {
  623.    return rcvlen;
  624.    }
  625.  
  626.  
  627. /* returns -2 for break, -1 if no char ready */
  628. int get_232(void)
  629. {
  630.     int c;
  631.  
  632.     if ( rcvlen )
  633.         {
  634.         if ( sio_brkmode && sio_break )
  635.             {
  636.             sio_break=0;
  637.             return-2;
  638.             }
  639.  
  640.         c=get_rcv_que();
  641.         }
  642.     else
  643.         c=-1;
  644.  
  645.     return c;
  646. }
  647.  
  648.  
  649. /* ---------------------- peek_232() ------------------ November 19,1992 */
  650. int peek_232(void)
  651. {
  652.     int c;
  653.  
  654.     if ( rcvlen == 0 )
  655.         return(-1);
  656.  
  657.     c=rcvbuf[rcvhead];
  658.  
  659.     return(c);
  660.  
  661. }
  662.  
  663. /* ---------------------- peek_232x() ------------------ October 21,1993 */
  664. int peek_232x(void)
  665. {
  666.     int c;
  667.  
  668.     if ( xmitlen == 0 )
  669.         return(-1);
  670.  
  671.     c=xmitbuf[xmithead];
  672.  
  673.     return(c);
  674.  
  675. }
  676.  
  677.  
  678. /* wait for char returns -2 for break */
  679. int get_232_wait(void)
  680. {
  681.     int c;
  682.  
  683.     while ( rcvlen == 0 )
  684.         if ( sio_brkmode && sio_break )
  685.             {
  686.             sio_break=0;
  687.             return-2;
  688.             }
  689.  
  690.     c=get_rcv_que();
  691.  
  692.     return c;
  693. }
  694.  
  695.  
  696.  
  697. /*
  698.    startup comport.
  699.    You can specify the comport (1,2,3,4) or a port address
  700.    (i.e. 0x3f8). If you specify a port you must specify irq.
  701.    If you specify the comport and irq is zero, the default is
  702.    used.
  703.  
  704.    CANNOT BE CALLED TWICE
  705.  
  706.    IF YOU WANT TO CALL IT AGAIN CALL deinit_232() first!!!
  707.  
  708. */
  709.  
  710. int init_232(serial_232_t *sr)
  711. {
  712.     int com; 
  713.     // unsigned far *peekad;
  714.     unsigned cntlword;
  715.  
  716.     /* point to table of COM addresses */
  717.     // peekad=MK_FP(0x40,0);
  718.     if ( sr->comport >= 1 && sr->comport <= 4 )  /* comm 1 ..4 */
  719.         {
  720.         com=sr->comport - 1;
  721.         // uart_adrs=peekad[com];    /* get base address */
  722.         uart_adrs=irq_adr_table[com];    /* get base address */
  723.         if ( !uart_adrs )
  724.             {
  725.             sio_error=SIO_NO_COMM;
  726.             printf("no such comm port\n");
  727.             exit(1);
  728.             return 1;       /* not installed */
  729.             }
  730.  
  731.         /* set default IRQ */
  732.         /* set IRQ=4 for COM1/3, 3 for COM 2/4 */
  733.         if ( !sr->irq )
  734.             sr->irq=(com & 1) == 1 ? 3 : 4;
  735.         }
  736.     else
  737.         {
  738.         /* port Address, not comm1 .. 4 */
  739.         /* explicit I/O set must have IRQ */
  740.         if ( !sr->irq )
  741.             {
  742.             printf("bad IRQ number\n");
  743.             exit(1);
  744.             sio_error=SIO_NO_IRQ;
  745.             return 1;
  746.             }
  747.  
  748.         uart_adrs=sr->comport;
  749.         }
  750.  
  751.     if ( sr->baud < 0 || sr->baud > sizeof(baud_table)/sizeof(int) )
  752.         {
  753.         printf("Invalid Baud Rate\n");
  754.         exit(1);
  755.         sio_error=SIO_BAD_BAUD;
  756.         return 1;
  757.         }
  758.  
  759.     if ( sr->bits < 5 || sr->bits > 8 )
  760.         {
  761.         printf("Bad number of data bits\n");
  762.         exit(1);
  763.         sio_error=SIO_BAD_BITS;
  764.         return 1;
  765.         }
  766.     if ( sr->stops < 1 || sr->stops > 2 )
  767.         {
  768.         printf("bad number of stop bits\n");
  769.         exit(1);
  770.         return 1;
  771.         }
  772.     if ( sr->parity < 0 || sr->parity > 4 )
  773.         {
  774.         printf("Invalid parity\n");
  775.         exit(1);
  776.         sio_error=SIO_BAD_PARITY;
  777.         return 1;
  778.         }
  779.  
  780.     irqnum=sr->irq;
  781.  
  782.     /* calculate irq mask bit for PIC */
  783.     irqmask=1<<sr->irq;
  784.     oldirq=getvect(sr->irq+8);          /* get old IRQ vector */
  785.     setvect(sr->irq+8,comint);          /* instal serial interupt handler */
  786.     outportb(uart_adrs+LCR,0x83);       /* none/8/1 - DLAB set */
  787.  
  788.     /* set baud rate */
  789.     outportb(uart_adrs+DATA_REG,baud_table[sr->baud]&0xFF);
  790.     outportb(uart_adrs+IER,baud_table[sr->baud]>>8);
  791.  
  792.     /* calculate control word for LCR */
  793.     cntlword=(2*sr->parity-sr->parity?1:0)<<4;
  794.     cntlword|=2*(sr->stops-1);
  795.     cntlword|=sr->bits-5;
  796.     outportb(uart_adrs+LCR,cntlword);
  797.     outportb(uart_adrs+MCR,0xF);           /* enable interrupts */
  798.     outportb(uart_adrs+IER,0xF);
  799.     outportb(0x21,inportb(0x21)&~irqmask);
  800.  
  801.     return 0;
  802. }
  803.  
  804.  
  805. /*
  806.    CALL THIS FUNCTION BEFORE PROGRAM EXIT!
  807.  
  808.    or before calling init_232() for a second time
  809. */
  810. void deinit_232(void)
  811.    {
  812.    outportb(uart_adrs+IER,0);             /* clear UART interrupts */
  813.    outportb(uart_adrs+MCR,0);
  814.    outportb(0x21,inportb(0x21)|irqmask);  /* clear PIC */
  815.    setvect(irqnum+8,oldirq);              /* restore interrupt vector */
  816.    }
  817.  
  818. /* Send a break */
  819. void sio_sendbreak(void)
  820.    {
  821.    outportb(uart_adrs+LCR,inportb(uart_adrs+LCR)|0x40);
  822.    t_delay(BRKTIME);
  823.    outportb(uart_adrs+LCR,inportb(uart_adrs+LCR)&~0x40);
  824.    }
  825.  
  826. /* set DTR - never tested - let me know if it works :) */
  827. void sio_setdtr(short set)
  828. {
  829.    unsigned char mcr;
  830.  
  831.    mcr=inportb(uart_adrs + MCR);
  832.    if ( set )
  833.       mcr|=MCR_RTS;
  834.    else
  835.       mcr&= ~MCR_RTS;
  836.  
  837.    outportb(uart_adrs + MCR, mcr);
  838. }
  839.  
  840.  
  841. /* ----------------------- end of basic serial stuff ---------------- */
  842.  
  843. /* ================================================================== */
  844.  
  845.  
  846. /* end of serio.c ---------------------------------------------------- */
  847.